/******************************************************************************************
Copyright(C), 2019-2020, Linyar.
文件名：L_SVP_IVE_csc.c
作者：燕卫博    版本：V1.0    创建日期：2021.6.8
文件描述：
    SVP-IVE图像处理操作。
版本信息：
    9Hv2，个人。
历史修改记录：
1. 2021-6-8:V1.0 燕卫博
创建。

2. 2021-8-11:V1.0 燕卫博
从9Hv1拷贝，接续使用。
******************************************************************************************/
//                                              ↓
//+------------------------------------------------------------------------------------------+
//|                                       SVP-IVE操作说明
//+------------------------------------------------------------------------------------------+
//|      本文件仅为使用SVP-IVE进行图像格式转换操作的封装。
//+------------------------------------------------------------------------------------------+
//|  编写参考《HiIVE API参考(2019-8-5)》（简称《HiIVE》）、
//|  《HiMPP V4.0媒体处理软件开发参考(2019-8-1)》（简称《参考》）。
//+------------------------------------------------------------------------------------------+
//|                                         头文件包含
//+------------------------------------------------------------------------------------------+
/*|*/  #include "L_SVP_IVE_csc.h"
//+------------------------------------------------------------------------------------------+
//|                                          全局变量
//+------------------------------------------------------------------------------------------+
/*|*/  static IVE_IMAGE_S stInputYUV420SPImage = {0};
/*|*/  static IVE_CSC_CTRL_S stCscCtrl = {.enMode = IVE_CSC_MODE_VIDEO_BT601_YUV2RGB};
//+------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------------------------------+
//|  函数名称：L_SVP_IVE_CSC_Init
//|  功能描述：IVE_IMAGE_S结构体指针
//|  参数说明：IVE_IMAGE_S结构体指针
//|  返回值说明：成功返回0
//|  备注：固定值初始化，仅适用于当前工程。
//+------------------------------------------------------------------------------------------+
int L_SVP_IVE_CSC_Init(IVE_IMAGE_S *pstOutputRGB888Image)
{
    HI_S32 s32Ret = HI_SUCCESS;
    HI_U64 u64PhyAddr = 0;
    HI_U8 *pu8VirAddr = NULL;
    HI_U32 u32MMZSize = 0;

    pstOutputRGB888Image->enType = IVE_IMAGE_TYPE_U8C3_PLANAR;
    pstOutputRGB888Image->u32Width = 320;
    pstOutputRGB888Image->u32Height = 180;
    pstOutputRGB888Image->au32Stride[0] = SVP_IVE_ALIGN(320, 16);
    pstOutputRGB888Image->au32Stride[1] = SVP_IVE_ALIGN(320, 16);
    pstOutputRGB888Image->au32Stride[2] = SVP_IVE_ALIGN(320, 16);

    /* 第0段 */
    u32MMZSize = pstOutputRGB888Image->au32Stride[0] * pstOutputRGB888Image->u32Height;
    s32Ret = HI_MPI_SYS_MmzAlloc((HI_U64*)&u64PhyAddr, (void**)&pu8VirAddr, NULL, HI_NULL, u32MMZSize);
    if(s32Ret != HI_SUCCESS){LOGE("[SVP-IVE-ERROR]HI_MPI_SYS_MmzAlloc failed with %#x!\n", s32Ret);goto FAIL;}
    memset(pu8VirAddr, 0, u32MMZSize);
    pstOutputRGB888Image->au64PhyAddr[0] = u64PhyAddr;
    pstOutputRGB888Image->au64VirAddr[0] = (HI_U64)(HI_UL)pu8VirAddr;
    u64PhyAddr = 0;
    pu8VirAddr = NULL;

    /* 第1段 */
    u32MMZSize = pstOutputRGB888Image->au32Stride[1] * pstOutputRGB888Image->u32Height;
    s32Ret = HI_MPI_SYS_MmzAlloc((HI_U64*)&u64PhyAddr, (void**)&pu8VirAddr, NULL, HI_NULL, u32MMZSize);
    if(s32Ret != HI_SUCCESS){LOGE("[SVP-IVE-ERROR]HI_MPI_SYS_MmzAlloc failed with %#x!\n", s32Ret);goto FAIL;}
    memset(pu8VirAddr, 0, u32MMZSize);
    pstOutputRGB888Image->au64PhyAddr[1] = u64PhyAddr;
    pstOutputRGB888Image->au64VirAddr[1] = (HI_U64)(HI_UL)pu8VirAddr;
    u64PhyAddr = 0;
    pu8VirAddr = NULL;

    /* 第2段 */
    u32MMZSize = pstOutputRGB888Image->au32Stride[2] * pstOutputRGB888Image->u32Height;
    s32Ret = HI_MPI_SYS_MmzAlloc((HI_U64*)&u64PhyAddr, (void**)&pu8VirAddr, NULL, HI_NULL, u32MMZSize);
    if(s32Ret != HI_SUCCESS){LOGE("[SVP-IVE-ERROR]HI_MPI_SYS_MmzAlloc failed with %#x!\n", s32Ret);goto FAIL;}
    memset(pu8VirAddr, 0, u32MMZSize);
    pstOutputRGB888Image->au64PhyAddr[2] = u64PhyAddr;
    pstOutputRGB888Image->au64VirAddr[2] = (HI_U64)(HI_UL)pu8VirAddr;
    u64PhyAddr = 0;
    pu8VirAddr = NULL;

    return 0;
FAIL:
    L_SVP_IVE_CSC_DeInit(pstOutputRGB888Image);
    return -1;
}

//+------------------------------------------------------------------------------------------+
//|  函数名称：L_SVP_IVE_CSC
//|  功能描述：YUV2RGB
//|  参数说明：VIDEO_FRAME_INFO_S结构体指针和IVE_IMAGE_S结构体指针
//|  返回值说明：成功返回0
//|  备注：
//+------------------------------------------------------------------------------------------+
int L_SVP_IVE_CSC(VIDEO_FRAME_INFO_S *pstInputYUV420SPImage, IVE_IMAGE_S *pstOutputRGB888Image)
{
    HI_S32 s32Ret = HI_SUCCESS;
    IVE_HANDLE IveCscHandle;
    HI_BOOL bInstant = HI_TRUE;

    //------------------------------------------------------------
    // 数据类型与VPSS输出像素格式
    // ATTENTION:IVE_IMAGE_TYPE_YUV420SP类型的IVE_IMAGE_S图像，对
    //           于Hi3559AV100ES、Hi3559AV100、Hi3519AV100、
    //           Hi3516CV500、Hi3516EV200，格式与VIDEO_FRAME_S的
    //           PIXEL_FORMAT_YVU_SEMIPLANAR_420 对应，对于其他芯
    //           片，格式与PIXEL_FORMAT_YUV_SEMIPLANAR_420 对应。
    //           ——《HiIVE》P20
    //------------------------------------------------------------
    stInputYUV420SPImage.enType         = IVE_IMAGE_TYPE_YUV420SP;
    stInputYUV420SPImage.u32Width       = pstInputYUV420SPImage->stVFrame.u32Width;
    stInputYUV420SPImage.u32Height      = pstInputYUV420SPImage->stVFrame.u32Height;
    stInputYUV420SPImage.au32Stride[0]  = pstInputYUV420SPImage->stVFrame.u32Stride[0];
    stInputYUV420SPImage.au32Stride[1]  = pstInputYUV420SPImage->stVFrame.u32Stride[1];
    stInputYUV420SPImage.au32Stride[2]  = pstInputYUV420SPImage->stVFrame.u32Stride[2];
    stInputYUV420SPImage.au64PhyAddr[0] = pstInputYUV420SPImage->stVFrame.u64PhyAddr[0];
    stInputYUV420SPImage.au64PhyAddr[1] = pstInputYUV420SPImage->stVFrame.u64PhyAddr[1];
    stInputYUV420SPImage.au64PhyAddr[2] = pstInputYUV420SPImage->stVFrame.u64PhyAddr[2];
    stInputYUV420SPImage.au64VirAddr[0] = pstInputYUV420SPImage->stVFrame.u64VirAddr[0];
    stInputYUV420SPImage.au64VirAddr[1] = pstInputYUV420SPImage->stVFrame.u64VirAddr[1];
    stInputYUV420SPImage.au64VirAddr[2] = pstInputYUV420SPImage->stVFrame.u64VirAddr[2];

    s32Ret = HI_MPI_IVE_CSC(&IveCscHandle, &stInputYUV420SPImage, pstOutputRGB888Image, &stCscCtrl, bInstant);
    if(s32Ret != HI_SUCCESS){LOGE("[SVP-IVE-ERROR]HI_MPI_IVE_CSC failed with %#x!\n", s32Ret);return -1;}

    return 0;
}

//+------------------------------------------------------------------------------------------+
//|  函数名称：L_SVP_IVE_CSC_DeInit
//|  功能描述：释放所指向结构体持有的内存
//|  参数说明：IVE_IMAGE_S结构体指针
//|  返回值说明：无
//|  备注：
//+------------------------------------------------------------------------------------------+
void L_SVP_IVE_CSC_DeInit(IVE_IMAGE_S *pstOutputRGB888Image)
{
    /* 第0段 */
    if(0 != pstOutputRGB888Image->au64PhyAddr[0] && 0 != pstOutputRGB888Image->au64VirAddr[0])
    {
        HI_MPI_SYS_MmzFree(pstOutputRGB888Image->au64PhyAddr[0], (HI_VOID*)(HI_UL)pstOutputRGB888Image->au64VirAddr[0]);
        pstOutputRGB888Image->au64PhyAddr[0] = 0;
        pstOutputRGB888Image->au64VirAddr[0] = 0;
    }
    else
    {
        LOGD("[SVP-IVE-DEBUG]Free size is 0\n");
    }

    /* 第1段 */
    if(0 != pstOutputRGB888Image->au64PhyAddr[1] && 0 != pstOutputRGB888Image->au64VirAddr[1])
    {
        HI_MPI_SYS_MmzFree(pstOutputRGB888Image->au64PhyAddr[1], (HI_VOID*)(HI_UL)pstOutputRGB888Image->au64VirAddr[1]);
        pstOutputRGB888Image->au64PhyAddr[1] = 0;
        pstOutputRGB888Image->au64VirAddr[1] = 0;
    }
    else
    {
        LOGD("[SVP-IVE-DEBUG]Free size is 0\n");
    }

    /* 第2段 */
    if(0 != pstOutputRGB888Image->au64PhyAddr[2] && 0 != pstOutputRGB888Image->au64VirAddr[2])
    {
        HI_MPI_SYS_MmzFree(pstOutputRGB888Image->au64PhyAddr[2], (HI_VOID*)(HI_UL)pstOutputRGB888Image->au64VirAddr[2]);
        pstOutputRGB888Image->au64PhyAddr[2] = 0;
        pstOutputRGB888Image->au64VirAddr[2] = 0;
    }
    else
    {
        LOGD("[SVP-IVE-DEBUG]Free size is 0\n");
    }
}
